package com.ddwl.gate.util;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectListing;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.*;
import java.util.Base64;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author Fu Zhaohui
 * @version 1.0.0
 * @date 2019/2/12 17:28
 */
@Slf4j
@Component
public class OssUtil {


    @Value("${oss.admin.accessKey}")
    private String adminAccessKeyId;
    @Value("${oss.admin.accessSecret}")
    private String adminAccessKeySecret;
    @Value("${oss.admin.bucket}")
    private String adminBucket;

    @Value("${oss.sts.accessKey}")
    private String stsAccessKeyId;
    @Value("${oss.sts.accessSecret}")
    private String stsAccessKeySecret;
    @Value("${oss.sts.roleARN}")
    private String stsRoleArn;
    @Value("${oss.sts.policy}")
    private String stsPolicy;
    @Value("${oss.sts.prefix}")
    private String stsPrefix;

    @Value("${oss.endpoint}")
    private String endpoint;

    @Value("${oss.region:cn-hangzhou}")
    private String region;


    public Map<String, String> getSecurityToken() {
        String roleSessionName = "external-username";

        IClientProfile profile = DefaultProfile.getProfile(region, stsAccessKeyId, stsAccessKeySecret);
        // 用profile构造client
        DefaultAcsClient client = new DefaultAcsClient(profile);
        final AssumeRoleRequest request = new AssumeRoleRequest();
        request.setRoleSessionName(roleSessionName);
        request.setRoleArn(stsRoleArn);
        request.setPolicy(stsPolicy);
        request.setRoleSessionName(roleSessionName);

        try {
            AssumeRoleResponse response = client.getAcsResponse(request);
            Map<String, String> respMap = new LinkedHashMap<>();
            respMap.put("AccessKeyId", response.getCredentials().getAccessKeyId());
            respMap.put("AccessKeySecret", response.getCredentials().getAccessKeySecret());
            respMap.put("SecurityToken", response.getCredentials().getSecurityToken());
            respMap.put("Expiration", response.getCredentials().getExpiration());
            respMap.put("OssPrefix", stsPrefix);
            return respMap;
        } catch (ClientException e) {
            log.error("OSS STS", e);
        }
        return null;
    }


    public void createBucket(String bucketName, String securityToken) {
        OSSClient ossClient = getClient(securityToken);
        ossClient.createBucket(bucketName);
        ossClient.shutdown();
    }

    public void uploadFile(InputStream inputStream, String fileName, String bucketName, String securityToken) {
        OSSClient ossClient = getClient(securityToken);
        if (!StringUtils.hasText(bucketName)) {
            bucketName = adminBucket;
        }
        ossClient.putObject(bucketName, fileName, inputStream);
        ossClient.shutdown();
    }

    public void base64UploadFile(String base64Data, String fileName, String bucketName, String securityToken) {
        OSSClient ossClient = getClient(securityToken);
        if (!StringUtils.hasText(bucketName)) {
            bucketName = adminBucket;
        }
        // 图片数据解码
        byte[] bytes = Base64.getDecoder().decode(base64Data.getBytes());
        ossClient.putObject(bucketName, fileName, new ByteArrayInputStream(bytes));
        ossClient.shutdown();
    }

    public String base64UploadFileThenReturn(String base64Data, String fileName) {
        Map<String, String> map = getSecurityToken();
        OSS ossClient = new OSSClientBuilder().build(endpoint, map.get("AccessKeyId"), map.get("AccessKeySecret"), map.get("SecurityToken"));
        byte[] bytes = Base64.getDecoder().decode(base64Data.getBytes());
        ossClient.putObject(adminBucket, fileName, new ByteArrayInputStream(bytes));
        ossClient.shutdown();
        return stsPrefix + "/" + fileName;
    }

    public ObjectListing listObjects(String bucketName, String securityToken) {
        OSSClient ossClient = getClient(securityToken);
        if (!StringUtils.hasText(bucketName)) {
            bucketName = adminBucket;
        }
        ObjectListing objectListing = ossClient.listObjects(bucketName);
        ossClient.shutdown();
        return objectListing;
    }

    public void deleteFile(String fileName, String bucketName, String securityToken) {
        OSSClient ossClient = getClient(securityToken);
        if (!StringUtils.hasText(bucketName)) {
            bucketName = adminBucket;
        }
        ossClient.deleteObject(bucketName, fileName);
        ossClient.shutdown();
    }

    private OSSClient getClient(String securityToken) {
        DefaultCredentialProvider credential;
        if (StringUtils.hasText(securityToken)) {
            credential = new DefaultCredentialProvider(stsAccessKeyId, stsAccessKeySecret, securityToken);
        } else {
            credential = new DefaultCredentialProvider(adminAccessKeyId, adminAccessKeySecret);
        }
        return new OSSClient(endpoint, credential, null);
    }

    public void getOSSObject(File file, String fileName) {
        Map<String, String> map = getSecurityToken();
        OSS ossClient = new OSSClientBuilder().build(endpoint, map.get("AccessKeyId"), map.get("AccessKeySecret"), map.get("SecurityToken"));
        GetObjectRequest request = new GetObjectRequest(adminBucket, fileName);
        ossClient.getObject(request, file);
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    public String getOSSBase64(String fileName){
        Map<String, String> map = getSecurityToken();
        OSS ossClient = new OSSClientBuilder().build(endpoint, map.get("AccessKeyId"), map.get("AccessKeySecret"), map.get("SecurityToken"));
        OSSObject ossObject = ossClient.getObject(adminBucket, fileName);
        InputStream is = ossObject.getObjectContent();
        try {
            byte[] bytes = IOUtils.toByteArray(is);
            return Base64.getEncoder().encodeToString(bytes);
        } catch (IOException e) {
            log.error("获取oss文件流出错",e);
        }
        return null;
    }

}
